`ifndef MOTOR_DRIVER_SVH
`define MOTOR_DRIVER_SVH

class motor_driver;
    virtual motor_bfm bfm;
    /*
     * 静态属性
     */
    logic   [31:00]             pulse_cnt;  // 每圈产生的脉冲数量
    logic   [31:00]             round_per_min;  // 每分钟多少转


    longint                     pulse_width;  // ns

    function new(virtual motor_bfm b);  // 需要赋初值的属性
        bfm = b;
    endfunction

    /*
    * 假设1圈有163840个计数值，那么a, b相分别有163840/2  = 81920, 
    * 又因为双沿计数, 所以一圈有 81920/2 = 40960个周期

    * 假设需要电机每分转100圈, 1000000000*60/100/40960  = 14648.4375
    */
    extern task motor_config
        (   
            input logic [31:0] pulse_cnt = 163840,
            input logic [31:0] round_per_min = 100
        );

    /*-------------------------------------------------------------------------
    //description   :   配置电机运动参数
    // direct : 1, 正转； 0, 反转
    // number : 转动的细分个数, 例如想让电机转5圈，则number = pulse_cnt * 5
    -------------------------------------------------------------------------*/
    extern task turn_round(int direct, int number);

    /*-------------------------------------------------------------------------
    //description   :   摆动工作模式, 不支持穿越零位的摆动
    // angle1 : 摆动起始角度
    // angle2 : 摆动结束角度
    // number : 摆动的次数
    -------------------------------------------------------------------------*/
    extern task turn_sway(int angle1, int angle2, int number);


    task phase_a_run (int width, int number);
        for(int i = 0; i < number/4; i++)
        begin
            bfm.phase_a = 1; #(width*2);
            bfm.phase_a = 0; #(width*2);
        end
    endtask

    task phase_b_run (int width, int number);
        for(int i = 0; i < number/4; i++)
        begin
            bfm.phase_b = 1; #(width*2);
            bfm.phase_b = 0; #(width*2);
        end
    endtask

    task phase_z_run (int width, int number);
        for(int i = 0; i < number; i++)
        begin
            bfm.phase_z = 1; #(width);
            bfm.phase_z = 0; #(width);
        end
    endtask
endclass

task motor_driver::motor_config
(   
    input logic [31:0] pulse_cnt = 163840,
    input logic [31:0] round_per_min = 100
);
    this.pulse_cnt = pulse_cnt;
    this.round_per_min = round_per_min;
    // 1000000000 / ((7200/3600)*163840) = 3051.7578125
    // 1000000000 * 3600 / (7200 * 163840) = 3051.7578125
    // (1e9*60) / (1500*163840) = 244.140625
    this.pulse_width =  (1000_000_000*60) / (this.round_per_min*this.pulse_cnt);
endtask

task motor_driver::turn_round(int direct, int number);
    if(direct)
    begin
        while(number >= this.pulse_cnt)
        begin
            // $display("pulse_cnt = %d", this.pulse_cnt);
            // $display("number = %d", number);
            fork
                begin
                    this.phase_z_run(this.pulse_width, 1);
                end
                begin
                    this.phase_a_run(this.pulse_width, this.pulse_cnt);
                end
                begin
                    #(this.pulse_width);
                    this.phase_b_run(this.pulse_width, this.pulse_cnt);
                end
            join
            number = number - this.pulse_cnt;
        end
        fork
            begin
                this.phase_z_run(this.pulse_width, 1);
            end
            begin
                this.phase_a_run(this.pulse_width, this.pulse_cnt);
            end
            begin
                #(this.pulse_width/4);
                this.phase_b_run(this.pulse_width, this.pulse_cnt);
            end
        join
    end
    else
    begin
        while(number >= this.pulse_cnt)
        begin
            fork
                begin
                    this.phase_z_run(this.pulse_width, 1);
                end
                begin
                    this.phase_b_run(this.pulse_width, this.pulse_cnt);
                end
                begin
                    #(this.pulse_width/4);
                    this.phase_a_run(this.pulse_width, this.pulse_cnt);
                end
            join
            number = number - this.pulse_cnt;
        end
        fork
            begin
                this.phase_z_run(this.pulse_width, 1);
            end
            begin
                this.phase_b_run(this.pulse_width, this.pulse_cnt);
            end
            begin
                #(this.pulse_width/4);
                this.phase_a_run(this.pulse_width, this.pulse_cnt);
            end
        join
    end
endtask

task motor_driver::turn_sway(int angle1, int angle2, int number);
    int angle1_cnt = this.pulse_cnt * angle1/360 ;
    int angle2_cnt = this.pulse_cnt * angle2/360;

    // 开始角度之前正常转动
    fork
        begin
            this.phase_a_run(this.pulse_width, angle1);
        end
        begin
            #(this.pulse_width/4);
            this.phase_b_run(this.pulse_width, angle1);
        end
    join


    for(int m = 0; m < number; m = m + 1 )
    begin
        $display("%t ---------------start turn negedge----------------", $time());
        fork
            begin
                this.phase_a_run(this.pulse_width, angle2_cnt - angle1_cnt);
            end
            begin
                #(this.pulse_width/4);
                this.phase_b_run(this.pulse_width, angle2_cnt - angle1_cnt);
            end
        join
        $display("%t ---------------start turn negedge----------------", $time());
        fork
            begin
                this.phase_b_run(this.pulse_width, angle2_cnt - angle1_cnt);
            end
            begin
                #(this.pulse_width/4);
                this.phase_a_run(this.pulse_width, angle2_cnt - angle1_cnt);
            end
        join

    end
endtask
`endif
